<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>司机薪酬工具</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
        body { padding: 20px; background: #f5f7fa; min-height: 100vh; }
        .container { max-width: 600px; margin: 0 auto; }
        h1 { font-size: 24px; color: #2c3e50; text-align: center; margin-bottom: 25px; }
        .card { background: white; border-radius: 12px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
        h2 { font-size: 18px; color: #2c3e50; margin-bottom: 15px; }
        .input-item { margin-bottom: 15px; }
        label { display: block; margin-bottom: 6px; font-size: 15px; color: #333; }
        select, input { width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 8px; font-size: 16px; }
        /* 输入框校验错误样式 */
        input.invalid { border-color: #ef4444 !important; }
        .calc-result { margin: 15px 0; padding: 12px; background: #e3f2fd; border-radius: 8px; text-align: center; }
        .calc-result span { font-size: 18px; color: #3498db; font-weight: bold; }
        .add-btn { background: #27ae60; color: white; border: none; padding: 12px; border-radius: 8px; font-size: 16px; width: 100%; cursor: pointer; }
        .task-list-container { 
            max-height: 300px; 
            overflow-y: auto; 
            border: 1px solid #eee; 
            border-radius: 8px; 
            padding: 10px; 
            margin-top: 10px;
            background: #fff;
        }
        .task-item { padding: 12px; border-bottom: 1px solid #eee; margin-bottom: 8px; border-radius: 6px; background: #fafafa; display: flex; flex-direction: column; }
        .task-row { display: flex; justify-content: space-between; align-items: center; }
        .delete-btn { 
            background: #3498db; 
            color: white; 
            border: none; 
            padding: 6px 10px; 
            border-radius: 6px; 
            font-size: 12px; 
            cursor: pointer; 
            min-width: 70px;
            transition: all 0.3s ease;
        }
        .delete-btn.confirm {
            background: #e74c3c;
            animation: pulse 0.5s;
        }
        .delete-all-btn, .data-op-btn {
            background: #3498db;
            color: white;
            border: none;
            padding: 12px;
            border-radius: 8px;
            font-size: 16px;
            width: 100%;
            cursor: pointer;
            margin-top: 15px;
            transition: all 0.3s ease;
        }
        .delete-all-btn.confirm {
            background: #e74c3c;
            animation: pulse 0.5s;
        }
        .data-op-group {
            display: flex;
            gap: 10px;
            margin-top: 15px;
        }
        .data-op-btn {
            margin-top: 0;
            flex: 1;
        }
        .data-op-btn.export { background: #27ae60; }
        .data-op-btn.import { background: #f39c12; }
        #importFile { display: none; }
        @keyframes pulse {
            0% { transform: scale(1); }
            50% { transform: scale(1.05); }
            100% { transform: scale(1); }
        }
        .task-info { margin-bottom: 8px; font-size: 14px; }
        .task-amount { color: #e74c3c; font-weight: bold; font-size: 16px; }
        .empty { text-align: center; padding: 30px 0; color: #999; font-size: 16px; }
        .tip { position: fixed; top: 20px; left: 50%; transform: translateX(-50%); background: #4CAF50; color: white; padding: 12px 24px; border-radius: 8px; font-size: 16px; z-index: 1000; }
        .stats-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 20px; }
        .stat-card { background: #f8f9fa; padding: 12px; border-radius: 8px; text-align: center; }
        .stat-card p { font-size: 14px; color: #6c757d; margin-bottom: 5px; }
        .stat-card span { font-size: 16px; font-weight: bold; }
        .chart-wrapper { height: 220px; margin-top: 15px; }
        
        /* 时间筛选统计窗口样式 */
        .date-filter-section {
            margin: 20px 0;
            padding: 15px;
            background: #f0f7ff;
            border-radius: 8px;
        }
        .date-filter-section h3 {
            font-size: 16px;
            color: #2c3e50;
            margin-bottom: 12px;
            text-align: center;
        }
        .date-filter-controls {
            display: flex;
            gap: 10px;
            margin-bottom: 12px;
        }
        .date-filter-controls input {
            flex: 1;
            padding: 10px;
            font-size: 14px;
        }
        .date-filter-result {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 10px;
        }
        
        /* 滚动条样式 */
        .task-list-container::-webkit-scrollbar {
            width: 8px;
        }
        .task-list-container::-webkit-scrollbar-track {
            background: #f1f1f1;
            border-radius: 4px;
        }
        .task-list-container::-webkit-scrollbar-thumb {
            background: #c1c1c1;
            border-radius: 4px;
        }
        .task-list-container::-webkit-scrollbar-thumb:hover {
            background: #a8a8a8;
        }

        /* 高级设置卡片样式 */
        .settings-scroll { max-height: 35vh; overflow-y: auto; }
        .success-tip { color: #10b981; font-size: 0.75rem; margin: 0; animation: fadeInOut 3s ease forwards; }
        .error-tip { color: #ef4444; font-size: 0.75rem; margin: 0; }
        @keyframes fadeInOut { 0% { opacity: 0; } 20% { opacity: 1; } 80% { opacity: 1; } 100% { opacity: 0; } }
        .mt-4 { margin-top: 16px; }
        .advanced-settings-header {
            cursor: pointer;
            user-select: none;
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 12px 15px;
            background: #f5f7fa;
            border-radius: 8px 8px 0 0;
            font-weight: 600;
            color: #2c3e50;
        }
        .advanced-settings-content {
            padding: 15px;
            border: 1px solid #eee;
            border-top: none;
            border-radius: 0 0 8px 8px;
            display: none;
        }
        .rule-btn-group {
            display: flex;
            gap: 10px;
            margin-top: 20px !important;
            margin-bottom: 15px;
        }
        .rule-btn {
            padding: 8px 12px !important;
            font-size: 14px !important;
            border-radius: 6px !important;
            color: white !important;
            border: none !important;
            cursor: pointer !important;
        }
        .rule-btn.confirm { background-color: #22c55e !important; }
        .rule-btn.add { background-color: #3b82f6 !important; }
        .rule-btn.del { background-color: #ef4444 !important; }
    </style>
</head>
<body>
    <div class="container">
        <h1>司机薪酬工具</h1>
        <div class="card" id="calcModule">
            <h2>计算区</h2>
            <div class="input-item">
                <label>任务类型</label>
                <select id="calcType">
                    <option value="loaded">载货任务</option>
                    <option value="empty">空驶任务</option>
                </select>
            </div>
            <div class="input-item">
                <label>行驶距离（公里）</label>
                <input type="number" id="calcDist" min="0.1" step="0.1" value="5" oninput="validateNumberInput(this, 'decimal')">
            </div>
            <div class="calc-result">
                计算结果：<span id="calcAmt">¥40.00</span>
            </div>
        </div>
        <div class="card" id="extraModule">
            <div class="input-item">
                <label>任务日期</label>
                <input type="date" id="taskDate">
            </div>
            <button class="add-btn" id="addBtn">添加任务到列表</button>
            <div style="margin-top: 30px;">
                <h3 style="font-size: 16px; margin-bottom: 10px;">收入统计</h3>
                <div class="stats-grid">
                    <div class="stat-card"><p>总任务数</p><span id="totalTasks">0</span></div>
                    <div class="stat-card"><p>总收入</p><span id="totalAmt">¥0.00</span></div>
                </div>
            </div>
            <div style="margin-top: 20px;">
                <h3 style="font-size: 16px; margin-bottom: 10px;">每周收入</h3>
                <div class="chart-wrapper"><canvas id="incomeChart"></canvas></div>
            </div>
            <!-- 时间筛选统计窗口 -->
            <div class="date-filter-section">
                <h3>时间筛选统计</h3>
                <div class="date-filter-controls">
                    <input type="date" id="filterStartDate" placeholder="开始日期">
                    <input type="date" id="filterEndDate" placeholder="结束日期">
                </div>
                <div class="date-filter-result">
                    <div class="stat-card">
                        <p>筛选任务数</p>
                        <span id="filteredTaskCount">0</span>
                    </div>
                    <div class="stat-card">
                        <p>筛选总收入</p>
                        <span id="filteredIncome">¥0.00</span>
                    </div>
                </div>
            </div>
            <div style="margin-top: 20px;">
                <h3 style="font-size: 16px; margin-bottom: 10px;">任务列表</h3>
                <div class="task-list-container">
                    <div id="taskList" class="task-list"><div class="empty">暂无任务</div></div>
                </div>
                <!-- 数据操作按钮组 -->
                <div class="data-op-group">
                    <button id="exportBtn" class="data-op-btn export">导出数据</button>
                    <button id="importBtn" class="data-op-btn import">导入数据</button>
                    <input type="file" id="importFile" accept=".json">
                </div>
                <button id="deleteAllBtn" class="delete-all-btn">全部删除</button>
            </div>
        </div>

        <!-- 高级设置卡片 -->
        <div class="card mt-4">
            <div id="advancedSettingsHeader" class="advanced-settings-header">
                <span>高级设置</span>
                <span id="advancedSettingsIcon">+</span>
            </div>
            <div id="advancedSettingsContent" class="advanced-settings-content">
                <div class="flex gap-2 mb-3">
                    <div class="flex-1">
                        <label class="block text-sm font-semibold mb-1">载货保底(元)</label>
                        <input type="number" id="adv-base-freight" value="40.00" step="0.01" min="0" oninput="validateNumberInput(this, 'decimal')">
                    </div>
                    <div class="flex-1">
                        <label class="block text-sm font-semibold mb-1">空驶保底(元)</label>
                        <input type="number" id="adv-base-empty" value="0.00" step="0.01" min="0" oninput="validateNumberInput(this, 'decimal')">
                    </div>
                </div>
                <div class="rule-btn-group">
                    <button id="adv-confirm-rule" class="rule-btn confirm">确认当前规则</button>
                    <button id="adv-add-rule" class="rule-btn add">添加区间</button>
                    <button id="adv-del-rule" class="rule-btn del">删除区间</button>
                </div>
                <div id="adv-tip-container" class="mb-2"></div>
                <div class="overflow-x-auto">
                    <table class="min-w-full border-collapse text-sm">
                        <thead><tr class="bg-gray-50"><<<th class="border p-1 text-left">区间结束(km)</</</th><<<th class="border p-1 text-left">载货单价(元/km)</</</th><<<th class="border p-1 text-left">空驶单价(元/km)</</</th></tr></thead>
                        <tbody id="adv-rule-table"></tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 全局工具函数：输入框数字校验（解决小数点问题）
        function validateNumberInput(inputEl, type = 'integer') {
            let value = inputEl.value.trim();
            // 规则：仅允许数字和1个小数点（decimal类型），或纯数字（integer类型）
            const reg = type === 'decimal' ? /^(\d+)(\.\d{0,2})?$/ : /^\d+$/;
            
            if (!reg.test(value) && value !== '' && value !== '无限') {
                inputEl.classList.add('invalid'); // 错误样式
                return false; // 无效输入
            }
            inputEl.classList.remove('invalid'); // 移除错误样式
            return true; // 有效输入
        }

        // 全局工具函数：防抖（解决oninput高频触发）
        function debounce(fn, delay = 200) {
            let timer = null;
            return function(...args) {
                clearTimeout(timer);
                timer = setTimeout(() => fn.apply(this, args), delay);
            };
        }

        // 工具函数：日期解析与格式化（确保导入日期有效）
        function parseDate(dateStr) {
            // 处理非标准格式（如2024/5/20 → 2024-05-20）
            if (dateStr.includes('/')) {
                dateStr = dateStr.split('/').map(part => part.padStart(2, '0')).join('-');
            }
            const parts = dateStr.split('-');
            if (parts.length !== 3) return new Date(NaN);
            const year = parseInt(parts[0], 10);
            const month = parseInt(parts[1], 10) - 1;
            const day = parseInt(parts[2], 10);
            const date = new Date(year, month, day);
            // 校验日期有效性（如2024-02-30是无效日期）
            return date.getFullYear() === year && date.getMonth() === month && date.getDate() === day ? date : new Date(NaN);
        }

        // 工具函数：获取当月周数
        function getWeekOfMonth(date) {
            const firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
            const firstDayOfWeek = firstDay.getDay() || 7;
            const weekNumber = Math.ceil((date.getDate() + firstDayOfWeek - 1) / 7);
            return Math.min(weekNumber - 1, 3);
        }

        // 1. 计算模块
        const CalcModule = (function() {
            const dom = { 
                type: document.getElementById('calcType'), 
                dist: document.getElementById('calcDist'), 
                amt: document.getElementById('calcAmt') 
            };
            
            const defaultRateTable = [
                { max: 10, rate: 1.6 },
                { max: 20, rate: 1.5 },
                { max: 40, rate: 1.2 },
                { max: 60, rate: 1.0 },
                { max: 100, rate: 0.8 },
                { max: 200, rate: 0.6 },
                { max: 500, rate: 0.3 },
                { max: Infinity, rate: 0.15 }
            ];

            let dynamicRules = [];
            let baseAmounts = { freight: 40.00, empty: 0.00 };

            function calculateLoadedAmount(dist) {
                if (isNaN(dist) || dist < 0) return baseAmounts.freight.toFixed(2); // 防御NaN
                
                if (dynamicRules.length === 0) {
                    let amt = 0;
                    let remainingDist = dist;
                    for (let i = 0; i < defaultRateTable.length && remainingDist > 0; i++) {
                        const segment = defaultRateTable[i];
                        const prevMax = i > 0 ? defaultRateTable[i-1].max : 0;
                        const segmentDist = Math.min(remainingDist, segment.max - prevMax);
                        amt += segmentDist * segment.rate;
                        remainingDist -= segmentDist;
                    }
                    return Math.max(amt, baseAmounts.freight).toFixed(2);
                }

                let total = 0;
                let prevEnd = 0;
                const validKm = parseFloat(dist);
                for (const r of dynamicRules) {
                    const currEnd = r.endKm;
                    const segmentKm = currEnd === Infinity 
                        ? (validKm > prevEnd ? validKm - prevEnd : 0) 
                        : (validKm <= currEnd ? validKm - prevEnd : currEnd - prevEnd);
                    total += segmentKm * r.freightRate;
                    prevEnd = currEnd;
                    if (validKm <= currEnd) break;
                }
                return Math.max(total, baseAmounts.freight).toFixed(2);
            }

            function calculateEmptyAmount(dist) {
                if (isNaN(dist) || dist < 0) return baseAmounts.empty.toFixed(2); // 防御NaN
                
                if (dynamicRules.length === 0) {
                    return (dist * 0.2).toFixed(2);
                }

                let total = 0;
                let prevEnd = 0;
                const validKm = parseFloat(dist);
                for (const r of dynamicRules) {
                    const currEnd = r.endKm;
                    const segmentKm = currEnd === Infinity 
                        ? (validKm > prevEnd ? validKm - prevEnd : 0) 
                        : (validKm <= currEnd ? validKm - prevEnd : currEnd - prevEnd);
                    total += segmentKm * r.emptyRate;
                    prevEnd = currEnd;
                    if (validKm <= currEnd) break;
                }
                return Math.max(total, baseAmounts.empty).toFixed(2);
            }

            function calculate(type, dist) {
                return type === 'empty' ? calculateEmptyAmount(dist) : calculateLoadedAmount(dist);
            }

            function updateResult() {
                const dist = parseFloat(dom.dist.value) || 0;
                const amt = calculate(dom.type.value, dist);
                dom.amt.textContent = `¥${amt}`;
            }

            // 防抖处理更新，避免高频触发
            const debouncedUpdateResult = debounce(updateResult, 150);

            function bindEvents() {
                dom.type.addEventListener('change', debouncedUpdateResult);
                dom.dist.addEventListener('input', (e) => {
                    if (validateNumberInput(e.target, 'decimal')) { // 先校验再更新
                        debouncedUpdateResult();
                    }
                });
            }

            function updateRules(rules, baseFreight, baseEmpty) {
                dynamicRules = rules || [];
                baseAmounts.freight = isNaN(baseFreight) ? 40.00 : baseFreight;
                baseAmounts.empty = isNaN(baseEmpty) ? 0.00 : baseEmpty;
                debouncedUpdateResult();
            }

            function init() { 
                const today = new Date();
                const yyyy = today.getFullYear();
                const mm = String(today.getMonth() + 1).padStart(2, '0');
                const dd = String(today.getDate()).padStart(2, '0');
                const todayStr = `${yyyy}-${mm}-${dd}`;
                document.getElementById('taskDate').value = todayStr;
                document.getElementById('filterStartDate').value = todayStr;
                document.getElementById('filterEndDate').value = todayStr;
                bindEvents(); 
                debouncedUpdateResult(); 
            }

            function getCurrentResult() {
                const type = dom.type.value;
                const dist = parseFloat(dom.dist.value) || 0;
                return {
                    type: type,
                    typeText: type === 'loaded' ? '载货任务' : '空驶任务',
                    dist: dist.toFixed(1),
                    amt: calculate(type, dist),
                    date: document.getElementById('taskDate').value,
                    id: Date.now().toString()
                };
            }

            return {
                init: init,
                getCurrentResult: getCurrentResult,
                updateRules: updateRules,
                getBaseAmounts: () => baseAmounts,
                getDynamicRules: () => dynamicRules
            };
        })();

        // 2. 任务管理+统计模块 - 根治导入无效
        const ExtraModule = (function() {
            const STORAGE_KEY = 'driverAllData';
            let taskData = [];
            let chart = null;

            const dom = {
                addBtn: document.getElementById('addBtn'),
                taskList: document.getElementById('taskList'),
                totalTasks: document.getElementById('totalTasks'),
                totalAmt: document.getElementById('totalAmt'),
                deleteAllBtn: document.getElementById('deleteAllBtn'),
                filterStartDate: document.getElementById('filterStartDate'),
                filterEndDate: document.getElementById('filterEndDate'),
                filteredTaskCount: document.getElementById('filteredTaskCount'),
                filteredIncome: document.getElementById('filteredIncome'),
                exportBtn: document.getElementById('exportBtn'),
                importBtn: document.getElementById('importBtn'),
                importFile: document.getElementById('importFile')
            };

            // 加载数据（含旧数据迁移）
            function loadDataFromStorage() {
                try {
                    const storedData = JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}');
                    
                    // 迁移旧数据
                    const oldTasks = JSON.parse(localStorage.getItem('driverTasks') || '[]');
                    const oldSettings = JSON.parse(localStorage.getItem('driverAdvancedSettings') || '{}');
                    if (oldTasks.length > 0 || (oldSettings.rules && oldSettings.rules.length > 0)) {
                        const migratedRules = (oldSettings.rules || AdvancedSettingsModule.getDefaultRules()).map(rule => ({
                            ...rule,
                            endKm: rule.endKm === null || rule.endKm === undefined ? Infinity : rule.endKm,
                            freightRate: isNaN(rule.freightRate) ? 0 : rule.freightRate,
                            emptyRate: isNaN(rule.emptyRate) ? 0 : rule.emptyRate
                        }));
                        const migratedData = {
                            tasks: oldTasks.map(task => formatTaskData(task)), // 格式化任务
                            settings: {
                                rules: migratedRules,
                                baseFreight: isNaN(oldSettings.baseFreight) ? 40.00 : oldSettings.baseFreight,
                                baseEmpty: isNaN(oldSettings.baseEmpty) ? 0.00 : oldSettings.baseEmpty
                            }
                        };
                        saveDataToStorage(migratedData);
                        localStorage.removeItem('driverTasks');
                        localStorage.removeItem('driverAdvancedSettings');
                        showTip('数据迁移成功！旧数据已整合');
                    }

                    // 正常加载合并数据
                    const storedTasks = storedData.tasks || [];
                    const storedSettings = storedData.settings || {};
                    // 格式化任务数据（补全字段+校验）
                    taskData = storedTasks.map(task => formatTaskData(task));
                    // 处理设置中的无效值
                    if (storedSettings.rules) {
                        storedSettings.rules = storedSettings.rules.map(rule => ({
                            ...rule,
                            endKm: rule.endKm === null || rule.endKm === undefined || isNaN(Number(rule.endKm)) ? Infinity : rule.endKm,
                            freightRate: isNaN(rule.freightRate) ? 0 : rule.freightRate,
                            emptyRate: isNaN(rule.emptyRate) ? 0 : rule.emptyRate
                        }));
                        saveDataToStorage({ tasks: taskData, settings: storedSettings });
                    }
                } catch (e) {
                    console.error('加载数据失败', e);
                    taskData = [];
                    saveDataToStorage({ tasks: [], settings: { rules: AdvancedSettingsModule.getDefaultRules(), baseFreight: 40.00, baseEmpty: 0.00 } });
                }
            }

            // 格式化任务数据（补全字段+校验）
            function formatTaskData(task) {
                // 补全所有必要字段，确保无缺失
                const defaultDate = new Date().toISOString().split('T')[0];
                return {
                    id: task.id || Date.now().toString(),
                    type: task.type || 'loaded',
                    typeText: task.typeText || (task.type === 'empty' ? '空驶任务' : '载货任务'),
                    dist: isNaN(parseFloat(task.dist)) ? '0.0' : parseFloat(task.dist).toFixed(1),
                    amt: isNaN(parseFloat(task.amt)) ? '0.00' : parseFloat(task.amt).toFixed(2),
                    date: parseDate(task.date).toString() !== 'Invalid Date' ? task.date : defaultDate
                };
            }

            // 保存数据到本地存储
            function saveDataToStorage(customData = null) {
                try {
                    const saveData = customData || {
                        tasks: taskData,
                        settings: {
                            rules: AdvancedSettingsModule.getActiveRules().rules.map(rule => ({
                                ...rule,
                                endKm: rule.endKm === null || rule.endKm === undefined ? Infinity : rule.endKm,
                                freightRate: isNaN(rule.freightRate) ? 0 : rule.freightRate,
                                emptyRate: isNaN(rule.emptyRate) ? 0 : rule.emptyRate
                            })),
                            baseFreight: AdvancedSettingsModule.getActiveRules().baseFreight,
                            baseEmpty: AdvancedSettingsModule.getActiveRules().baseEmpty
                        }
                    };
                    localStorage.setItem(STORAGE_KEY, JSON.stringify(saveData));
                } catch (e) {
                    console.error('保存数据失败', e);
                    showTip('数据保存失败，请刷新页面重试');
                }
            }

            // 初始化图表
            function initChart() {
                try {
                    chart = new Chart(document.getElementById('incomeChart').getContext('2d'), {
                        type: 'bar',
                        data: { 
                            labels: ['第1周','第2周','第3周','第4周'], 
                            datasets: [{ 
                                label: '收入', 
                                data: [0,0,0,0], 
                                backgroundColor: 'rgba(54,162,235,0.6)' 
                            }] 
                        },
                        options: { 
                            responsive: true, 
                            maintainAspectRatio: false, 
                            scales: { y: { beginAtZero: true } }
                        }
                    });
                } catch (e) {
                    console.error('初始化图表失败', e);
                    chart = null;
                }
            }

            // 计算筛选统计
            function calculateFilteredStats() {
                const startDate = parseDate(dom.filterStartDate.value);
                const endDate = parseDate(dom.filterEndDate.value);
                
                if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
                    dom.filteredTaskCount.textContent = '0';
                    dom.filteredIncome.textContent = '¥0.00';
                    return;
                }

                const filteredTasks = taskData.filter(task => {
                    const taskDate = parseDate(task.date);
                    return !isNaN(taskDate.getTime()) && taskDate >= startDate && taskDate <= endDate;
                });

                const taskCount = filteredTasks.length;
                const totalIncome = filteredTasks.reduce((sum, task) => sum + parseFloat(task.amt), 0).toFixed(2);
                dom.filteredTaskCount.textContent = taskCount;
                dom.filteredIncome.textContent = `¥${totalIncome}`;
            }

            // 渲染任务列表（强制刷新）
            function renderTaskList() {
                try {
                    if (taskData.length === 0) {
                        dom.taskList.innerHTML = '<div class="empty">暂无任务</div>';
                        dom.deleteAllBtn.style.display = 'none';
                        calculateFilteredStats();
                        return;
                    }
                    
                    dom.deleteAllBtn.style.display = 'block';
                    const taskHtml = taskData.map(task => `
                        <div class="task-item">
                            <div class="task-info">${task.typeText} | ${task.date} | ${task.dist}公里</div>
                            <div class="task-row">
                                <div class="task-amount">¥${task.amt}</div>
                                <button class="delete-btn" data-id="${task.id}">删除</button>
                            </div>
                        </div>
                    `).join('');
                    dom.taskList.innerHTML = taskHtml;
                    calculateFilteredStats();
                } catch (e) {
                    console.error('渲染任务列表失败', e);
                    dom.taskList.innerHTML = '<div class="empty">任务加载失败，请刷新页面</div>';
                }
            }

            // 更新统计
            function updateStats() {
                try {
                    const count = taskData.length;
                    const total = taskData.reduce((sum, task) => sum + parseFloat(task.amt), 0).toFixed(2);
                    dom.totalTasks.textContent = count;
                    dom.totalAmt.textContent = `¥${total}`;

                    // 更新图表
                    const weekly = [0,0,0,0];
                    const currentMonth = new Date().getMonth();
                    const currentYear = new Date().getFullYear();
                    
                    taskData.forEach(task => {
                        const taskDate = parseDate(task.date);
                        if (!isNaN(taskDate.getTime()) && taskDate.getMonth() === currentMonth && taskDate.getFullYear() === currentYear) {
                            const weekIndex = getWeekOfMonth(taskDate);
                            weekly[weekIndex] += parseFloat(task.amt);
                        }
                    });

                    if (chart) {
                        chart.data.datasets[0].data = weekly;
                        chart.update();
                    } else {
                        initChart(); // 图表初始化失败时重试
                        if (chart) chart.data.datasets[0].data = weekly;
                    }
                    calculateFilteredStats();
                } catch (e) {
                    console.error('更新统计失败', e);
                }
            }

            // 添加任务
            function addTask() {
                try {
                    const taskInfo = CalcModule.getCurrentResult();
                    if (!taskInfo.date || parseFloat(taskInfo.dist) <= 0) { 
                        showTip('请选择日期并输入有效距离！'); 
                        return; 
                    }
                    
                    taskData.unshift(formatTaskData(taskInfo)); // 格式化后添加
                    saveDataToStorage();
                    renderTaskList();
                    updateStats();
                    showTip('任务添加成功！');
                } catch (e) {
                    console.error('添加任务失败', e);
                    showTip('任务添加失败，请重试');
                }
            }

            // 删除单个任务
            function deleteTask(taskId) {
                try {
                    const initialLength = taskData.length;
                    taskData = taskData.filter(task => task.id !== taskId);
                    
                    if (taskData.length !== initialLength) {
                        saveDataToStorage();
                        renderTaskList();
                        updateStats();
                        showTip('任务删除成功！');
                    }
                } catch (e) {
                    console.error('删除任务失败', e);
                    showTip('任务删除失败，请重试');
                }
            }

            // 删除所有任务
            function deleteAllTasks() {
                try {
                    if (taskData.length === 0) {
                        showTip('没有任务可删除！');
                        return;
                    }
                    
                    taskData = [];
                    saveDataToStorage();
                    renderTaskList();
                    updateStats();
                    showTip('所有任务已删除！');
                } catch (e) {
                    console.error('删除所有任务失败', e);
                    showTip('删除失败，请重试');
                }
            }

            // 导出数据
            function exportData() {
                try {
                    const exportData = JSON.parse(localStorage.getItem(STORAGE_KEY) || '{"tasks":[],"settings":{}}');
                    // 处理导出数据中的无效值
                    if (exportData.settings.rules) {
                        exportData.settings.rules = exportData.settings.rules.map(rule => ({
                            ...rule,
                            endKm: rule.endKm === Infinity ? '无限' : rule.endKm, // 友好显示
                            freightRate: isNaN(rule.freightRate) ? 0 : rule.freightRate,
                            emptyRate: isNaN(rule.emptyRate) ? 0 : rule.emptyRate
                        }));
                    }
                    const jsonStr = JSON.stringify(exportData, null, 2);
                    const blob = new Blob([jsonStr], { type: 'application/json' });
                    const url = URL.createObjectURL(blob);
                    const a = document.createElement('a');
                    a.href = url;
                    a.download = `司机薪酬数据_${new Date().toLocaleDateString()}.json`;
                    a.click();
                    URL.revokeObjectURL(url);
                    showTip('数据导出成功！');
                } catch (e) {
                    console.error('导出数据失败', e);
                    showTip('导出失败，请重试');
                }
            }

            // 根治导入无效：强校验+强制覆盖+全量刷新
            function importData(file) {
                if (!file.name.endsWith('.json')) {
                    showTip('导入失败：仅支持JSON格式文件！');
                    return;
                }

                const reader = new FileReader();
                reader.onload = function(e) {
                    try {
                        // 1. 解析JSON（容错处理）
                        let importedData;
                        try {
                            importedData = JSON.parse(e.target.result);
                        } catch (parseErr) {
                            throw new Error('JSON格式错误，无法解析');
                        }

                        // 2. 强校验数据结构
                        if (!importedData.tasks || !Array.isArray(importedData.tasks)) {
                            throw new Error('必须包含tasks数组');
                        }
                        if (!importedData.settings || !Array.isArray(importedData.settings.rules)) {
                            throw new Error('必须包含settings.rules数组');
                        }

                        // 3. 格式化导入数据（补全字段+校验）
                        const processedTasks = importedData.tasks.map(task => formatTaskData(task));
                        const processedRules = importedData.settings.rules.map(rule => {
                            // 处理区间结束值（“无限”转Infinity）
                            let endKm = rule.endKm === '无限' || rule.endKm === null || rule.endKm === undefined ? Infinity : Number(rule.endKm);
                            endKm = isNaN(endKm) ? Infinity : endKm;
                            return {
                                endKm: endKm,
                                freightRate: isNaN(Number(rule.freightRate)) ? 0 : Number(rule.freightRate),
                                emptyRate: isNaN(Number(rule.emptyRate)) ? 0 : Number(rule.emptyRate)
                            };
                        });
                        const processedSettings = {
                            ...importedData.settings,
                            rules: processedRules,
                            baseFreight: isNaN(Number(importedData.settings.baseFreight)) ? 40.00 : Number(importedData.settings.baseFreight),
                            baseEmpty: isNaN(Number(importedData.settings.baseEmpty)) ? 0.00 : Number(importedData.settings.baseEmpty)
                        };

                        // 4. 强制覆盖数据（清空旧数据）
                        taskData = []; // 先清空，避免旧数据干扰
                        taskData = processedTasks;
                        saveDataToStorage({ tasks: taskData, settings: processedSettings });

                        // 5. 全量刷新所有界面（确保生效）
                        AdvancedSettingsModule.loadSettingsFromImport(processedSettings);
                        renderTaskList(); // 刷新任务列表
                        updateStats(); // 刷新统计
                        if (chart) {
                            chart.destroy(); // 重建图表，避免缓存
                        }
                        initChart(); // 重新初始化图表
                        showTip(`数据导入成功！共导入${taskData.length}个任务`);

                        // 6. 滚动到任务列表，直观显示
                        dom.taskList.scrollIntoView({ behavior: 'smooth' });
                    } catch (err) {
                        showTip(`导入失败：${err.message}`);
                        console.error('导入错误', err);
                    }
                };
                reader.onerror = function() {
                    showTip('导入失败：文件读取错误，请重新选择');
                };
                reader.readAsText(file);
            }

            // 显示提示
            function showTip(text) {
                const tip = document.createElement('div'); 
                tip.className = 'tip'; 
                tip.textContent = text;
                document.body.appendChild(tip); 
                setTimeout(() => tip.remove(), 2000);
            }

            // 绑定事件
            function bindEvents() {
                // 添加任务
                dom.addBtn.addEventListener('click', addTask);

                // 删除单个任务
                dom.taskList.addEventListener('click', (e) => {
                    if (e.target.classList.contains('delete-btn')) {
                        const button = e.target;
                        const taskId = button.dataset.id;
                        
                        if (button.classList.contains('confirm')) {
                            deleteTask(taskId);
                        } else {
                            button.classList.add('confirm');
                            button.textContent = '确认删除';
                            setTimeout(() => {
                                if (button.classList.contains('confirm')) {
                                    button.classList.remove('confirm');
                                    button.textContent = '删除';
                                }
                            }, 3000);
                        }
                    }
                });

                // 删除所有任务
                dom.deleteAllBtn.addEventListener('click', function() {
                    const button = this;
                    if (button.classList.contains('confirm')) {
                        deleteAllTasks();
                        button.classList.remove('confirm');
                        button.textContent = '全部删除';
                    } else {
                        button.classList.add('confirm');
                        button.textContent = '确认全部删除';
                        setTimeout(() => {
                            if (button.classList.contains('confirm')) {
                                button.classList.remove('confirm');
                                button.textContent = '全部删除';
                            }
                        }, 5000);
                    }
                });

                // 日期筛选
                dom.filterStartDate.addEventListener('change', calculateFilteredStats);
                dom.filterEndDate.addEventListener('change', calculateFilteredStats);

                // 数据导出
                dom.exportBtn.addEventListener('click', exportData);

                // 数据导入
                dom.importBtn.addEventListener('click', () => {
                    dom.importFile.value = '';
                    dom.importFile.click();
                });
                dom.importFile.addEventListener('change', (e) => {
                    const file = e.target.files[0];
                    if (file) importData(file);
                });
            }

            // 初始化
            function init() {
                try {
                    loadDataFromStorage();
                    bindEvents();
                    initChart();
                    renderTaskList();
                    updateStats();
                    calculateFilteredStats();
                } catch (e) {
                    console.error('初始化失败', e);
                    showTip('页面初始化失败，请刷新重试');
                }
            }

            return { 
                init: init,
                taskData: () => taskData,
                saveDataToStorage: saveDataToStorage,
                renderTaskList: renderTaskList,
                updateStats: updateStats,
                getChart: () => chart
            };
        })();

        // 3. 高级设置模块 - 根治闪退（小数点+输入校验）
        const AdvancedSettingsModule = (function() {
            const DEFAULT_SETTINGS = {
                rules: [
                    { endKm: 10, freightRate: 1.6, emptyRate: 0.2 },
                    { endKm: 20, freightRate: 1.5, emptyRate: 0.2 },
                    { endKm: 40, freightRate: 1.2, emptyRate: 0.2 },
                    { endKm: 60, freightRate: 1.0, emptyRate: 0.2 },
                    { endKm: 100, freightRate: 0.8, emptyRate: 0.2 },
                    { endKm: 200, freightRate: 0.6, emptyRate: 0.2 },
                    { endKm: 500, freightRate: 0.3, emptyRate: 0.2 },
                    { endKm: Infinity, freightRate: 0.15, emptyRate: 0.2 }
                ],
                baseFreight: 40.00, 
                baseEmpty: 0.00
            };

            let tempRules = [...DEFAULT_SETTINGS.rules];
            let activeRules = JSON.parse(JSON.stringify(tempRules));
            let baseFreight = DEFAULT_SETTINGS.baseFreight;
            let baseEmpty = DEFAULT_SETTINGS.baseEmpty;

            const dom = {
                settingsHeader: document.getElementById('advancedSettingsHeader'),
                settingsContent: document.getElementById('advancedSettingsContent'),
                settingsIcon: document.getElementById('advancedSettingsIcon'),
                ruleTable: document.getElementById('adv-rule-table'),
                confirmRuleBtn: document.getElementById('adv-confirm-rule'),
                addRuleBtn: document.getElementById('adv-add-rule'),
                delRuleBtn: document.getElementById('adv-del-rule'),
                tipContainer: document.getElementById('adv-tip-container'),
                baseFreight: document.getElementById('adv-base-freight'),
                baseEmpty: document.getElementById('adv-base-empty'),
            };

            // 加载设置
            function loadSettingsFromStorage() {
                try {
                    const storedData = JSON.parse(localStorage.getItem('driverAllData') || '{}');
                    const storedSettings = storedData.settings || {};
                    
                    if (Array.isArray(storedSettings.rules) && storedSettings.rules.length > 0) {
                        tempRules = storedSettings.rules.map(rule => ({
                            endKm: rule.endKm === '无限' || rule.endKm === null || rule.endKm === undefined ? Infinity : Number(rule.endKm),
                            freightRate: isNaN(Number(rule.freightRate)) ? 0 : Number(rule.freightRate),
                            emptyRate: isNaN(Number(rule.emptyRate)) ? 0 : Number(rule.emptyRate)
                        }));
                        activeRules = JSON.parse(JSON.stringify(tempRules));
                    }
                    if (typeof storedSettings.baseFreight === 'number') {
                        baseFreight = storedSettings.baseFreight;
                    }
                    if (typeof storedSettings.baseEmpty === 'number') {
                        baseEmpty = storedSettings.baseEmpty;
                    }

                    dom.baseFreight.value = baseFreight;
                    dom.baseEmpty.value = baseEmpty;
                    renderTable();
                } catch (e) {
                    console.error('加载设置失败', e);
                    tempRules = [...DEFAULT_SETTINGS.rules];
                    activeRules = JSON.parse(JSON.stringify(tempRules));
                    renderTable();
                }
            }

            // 从导入加载设置
            function loadSettingsFromImport(importedSettings) {
                try {
                    if (Array.isArray(importedSettings.rules) && importedSettings.rules.length > 0) {
                        tempRules = importedSettings.rules.map(rule => ({
                            endKm: rule.endKm === '无限' || rule.endKm === null || rule.endKm === undefined ? Infinity : Number(rule.endKm),
                            freightRate: isNaN(Number(rule.freightRate)) ? 0 : Number(rule.freightRate),
                            emptyRate: isNaN(Number(rule.emptyRate)) ? 0 : Number(rule.emptyRate)
                        }));
                        activeRules = JSON.parse(JSON.stringify(tempRules));
                    }
                    if (typeof importedSettings.baseFreight === 'number') {
                        baseFreight = importedSettings.baseFreight;
                    }
                    if (typeof importedSettings.baseEmpty === 'number') {
                        baseEmpty = importedSettings.baseEmpty;
                    }

                    dom.baseFreight.value = baseFreight;
                    dom.baseEmpty.value = baseEmpty;
                    renderTable();
                    CalcModule.updateRules(activeRules, baseFreight, baseEmpty);
                } catch (e) {
                    console.error('加载导入设置失败', e);
                    showTip('设置加载失败，使用默认规则');
                    tempRules = [...DEFAULT_SETTINGS.rules];
                    activeRules = JSON.parse(JSON.stringify(tempRules));
                    renderTable();
                    CalcModule.updateRules(activeRules, 40.00, 0.00);
                }
            }

            // 显示提示
            function showTip(type, text) {
                dom.tipContainer.innerHTML = '';
                const tip = document.createElement('p');
                tip.className = type === 'success' ? 'success-tip' : 'error-tip';
                tip.innerHTML = `${type === 'success' ? '✅' : '⚠️'} ${text}`;
                dom.tipContainer.appendChild(tip);
                if (type === 'success') setTimeout(() => dom.tipContainer.innerHTML = '', 3000);
            }

            // 渲染表格（输入框绑定校验+防抖）
            function renderTable() {
                try {
                    dom.ruleTable.innerHTML = '';
                    tempRules.forEach((rule, idx) => {
                        const endKmDisplay = rule.endKm === Infinity ? '无限' : rule.endKm;
                        const tr = document.createElement('tr');
                        tr.className = idx % 2 === 0 ? 'bg-white' : 'bg-gray-50';
                        // 输入框绑定校验+防抖更新
                        tr.innerHTML = `
                            <td class="border p-1">
                                <input type="text" value="${endKmDisplay}" class="w-full p-1 border rounded" 
                                    oninput="validateNumberInput(this, 'decimal')"
                                    onchange="AdvancedSettingsModule.debouncedUpdateRule(${idx}, 'endKm', this.value)">
                            </td>
                            <td class="border p-1">
                                <input type="number" step="0.01" min="0" value="${rule.freightRate}" class="w-full p-1 border rounded" 
                                    oninput="validateNumberInput(this, 'decimal')"
                                    onchange="AdvancedSettingsModule.debouncedUpdateRule(${idx}, 'freightRate', this.value)">
                            </td>
                            <td class="border p-1">
                                <input type="number" step="0.01" min="0" value="${rule.emptyRate}" class="w-full p-1 border rounded" 
                                    oninput="validateNumberInput(this, 'decimal')"
                                    onchange="AdvancedSettingsModule.debouncedUpdateRule(${idx}, 'emptyRate', this.value)">
                            </td>
                        `;
                        dom.ruleTable.appendChild(tr);
                    });
                } catch (e) {
                    console.error('渲染表格失败', e);
                    dom.ruleTable.innerHTML = '<tr><td colspan="3" class="text-center text-red-500">规则加载失败</td></tr>';
                }
            }

            // 验证规则
            function checkRule() {
                const validRules = tempRules.filter(r => r.endKm !== Infinity);
                // 检查区间递增
                for (let i = 1; i < validRules.length; i++) {
                    if (validRules[i].endKm <= validRules[i - 1].endKm) {
                        return { ok: false, tip: '区间需递增（如10→20→40）' };
                    }
                }
                // 检查单价非负
                for (const r of tempRules) {
                    if (r.freightRate < 0 || r.emptyRate < 0) {
                        return { ok: false, tip: '单价不能为负数' };
                    }
                }
                return { ok: true, tip: '新规则已生效' };
            }

            // 核心：防抖+强校验的规则更新（解决闪退）
            function updateRule(idx, key, value) {
                try {
                    // 1. 索引校验
                    if (idx < 0 || idx >= tempRules.length || !tempRules[idx]) {
                        console.warn('无效索引', idx);
                        return;
                    }

                    // 2. 输入值校验
                    let validValue = value;
                    if (key === 'endKm') {
                        // 区间结束：允许“无限”或数字（含小数点）
                        if (value === '无限' || value === '') {
                            validValue = Infinity;
                        } else {
                            validValue = parseFloat(value);
                            if (isNaN(validValue) || validValue < 0) {
                                showTip('error', '区间结束需为非负数字或“无限”');
                                renderTable(); // 重置输入框
                                return;
                            }
                        }
                    } else {
                        // 单价：仅允许非负数字（含小数点）
                        validValue = parseFloat(value);
                        if (isNaN(validValue) || validValue < 0) {
                            showTip('error', '单价需为非负数字');
                            renderTable(); // 重置输入框
                            return;
                        }
                    }

                    // 3. 更新规则
                    tempRules[idx][key] = validValue;
                    dom.tipContainer.innerHTML = '';
                    renderTable(); // 重新渲染，确保状态同步
                } catch (e) {
                    console.error('更新规则失败', e);
                    showTip('error', '规则更新失败，请重试');
                    renderTable(); // 出错后重置
                }
            }

            // 防抖包装更新函数（解决高频触发）
            const debouncedUpdateRule = debounce(updateRule, 200);

            // 折叠事件
            function bindCollapseEvent() {
                dom.settingsHeader.addEventListener('click', () => {
                    const isHidden = dom.settingsContent.style.display === 'none' || dom.settingsContent.style.display === '';
                    dom.settingsContent.style.display = isHidden ? 'block' : 'none';
                    dom.settingsIcon.textContent = isHidden ? '-' : '+';
                });
            }

            // 绑定事件
            function bindEvents() {
                bindCollapseEvent();

                // 确认规则
                dom.confirmRuleBtn.addEventListener('click', () => {
                    try {
                        // 校验保底金额
                        const newBaseFreight = parseFloat(dom.baseFreight.value);
                        const newBaseEmpty = parseFloat(dom.baseEmpty.value);
                        if (isNaN(newBaseFreight) || newBaseFreight < 0) {
                            showTip('error', '载货保底需为非负数字');
                            dom.baseFreight.classList.add('invalid');
                            return;
                        }
                        if (isNaN(newBaseEmpty) || newBaseEmpty < 0) {
                            showTip('error', '空驶保底需为非负数字');
                            dom.baseEmpty.classList.add('invalid');
                            return;
                        }
                        dom.baseFreight.classList.remove('invalid');
                        dom.baseEmpty.classList.remove('invalid');

                        baseFreight = newBaseFreight;
                        baseEmpty = newBaseEmpty;
                        const res = checkRule();
                        
                        if (res.ok) {
                            activeRules = JSON.parse(JSON.stringify(tempRules));
                            CalcModule.updateRules(activeRules, baseFreight, baseEmpty);
                            ExtraModule.saveDataToStorage();
                            showTip('success', res.tip);
                        } else {
                            showTip('error', res.tip);
                        }
                    } catch (e) {
                        console.error('确认规则失败', e);
                        showTip('error', '确认规则失败，请重试');
                    }
                });

                // 添加区间
                dom.addRuleBtn.addEventListener('click', () => {
                    try {
                        const last = tempRules[tempRules.length - 1];
                        const newEnd = last.endKm === Infinity ? 1000 : (last.endKm || 0) + 100;
                        tempRules.splice(tempRules.length - 1, 0, { endKm: newEnd, freightRate: 0, emptyRate: 0 });
                        renderTable();
                        dom.tipContainer.innerHTML = '';
                    } catch (e) {
                        console.error('添加区间失败', e);
                        showTip('error', '添加区间失败，请重试');
                    }
                });

                // 删除区间
                dom.delRuleBtn.addEventListener('click', () => {
                    try {
                        if (tempRules.length <= 2) {
                            showTip('error', '至少保留2个区间（含“无限”）');
                            return;
                        }
                        tempRules.splice(tempRules.length - 2, 1);
                        renderTable(); // 删除后立即渲染，避免旧索引
                        dom.tipContainer.innerHTML = '';
                    } catch (e) {
                        console.error('删除区间失败', e);
                        showTip('error', '删除区间失败，请重试');
                    }
                });

                // 保底金额输入校验
                dom.baseFreight.addEventListener('input', (e) => validateNumberInput(e.target, 'decimal'));
                dom.baseEmpty.addEventListener('input', (e) => validateNumberInput(e.target, 'decimal'));
            }

            // 初始化
            function init() {
                loadSettingsFromStorage();
                bindEvents();
                CalcModule.updateRules(activeRules, baseFreight, baseEmpty);
            }

            // 对外暴露（含防抖更新函数）
            return {
                init: init,
                updateRule: updateRule,
                debouncedUpdateRule: debouncedUpdateRule, // 暴露防抖更新函数
                getActiveRules: () => ({ rules: activeRules, baseFreight, baseEmpty }),
                getDefaultRules: () => [...DEFAULT_SETTINGS.rules],
                loadSettingsFromImport: loadSettingsFromImport,
                renderTable: renderTable
            };
        })();

        // 全局暴露高级设置方法
        window.AdvancedSettingsModule = AdvancedSettingsModule;

        // 页面加载初始化
        window.onload = function() { 
            try {
                CalcModule.init(); 
                ExtraModule.init(); 
                AdvancedSettingsModule.init(); 
            } catch (e) {
                console.error('页面初始化失败', e);
                alert('页面加载失败，请刷新重试');
            }
        };
    </script>
</body>
</html>
